# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

# default_platform(:ios)
fastlane_require 'circleci_artifact'
fastlane_version "2.93.1"

BUILD_PATH="./build"
DERIVED_DATA_PATH = "#{BUILD_PATH}/derived_data"
PROJECT_NAME='BonMot.xcodeproj'

desc "Tests & Coverage: iOS, tvOS, macOS. Builds: watchOS."
lane :coverage_all do
  bundle_ios = coverage(scheme: "BonMot-iOS", devices: get_devices())
  bundle_tvos = coverage(scheme: "BonMot-tvOS")
  # For some reason fastlane tries to build for tvOS simulator unless destination is manually set
  bundle_macos = coverage(scheme: "BonMot-OSX", destination: "platform=macOS")
  
  xchtmlreport(result_bundle_paths: [bundle_ios, bundle_tvos, bundle_macos],
               enable_junit: true)
  # Unit testing is not available on watchOS
  xcodebuild(scheme: "BonMot-watchOS",
             derivedDataPath: DERIVED_DATA_PATH)
end

desc "Tests: iOS, tvOS, macOS. Builds: watchOS."
lane :test_all do
  test(scheme: "BonMot-iOS", devices: get_devices())
  test(scheme: "BonMot-OSX", destination: "platform=macOS")
  test(scheme: "BonMot-tvOS")
  # Unit testing is not available on watchOS
  xcodebuild(scheme: "BonMot-watchOS",
             derivedDataPath: DERIVED_DATA_PATH)
end

platform :mac do
  desc "Runs Tests & Generates Code Coverage Reports for macOS"
  lane :coverage_macos do
    coverage(scheme: "BonMot-OSX")
  end

  desc "Runs Tests for macOS"
  lane :test_macos do
    test(scheme: "BonMot-OSX", destination: "platform=macOS")
  end
end

platform :ios do
  desc "Runs Tests & Generates Code Coverage Reports for latest iOS"
  lane :coverage_ios do
    devices = get_devices()
    coverage(scheme: "BonMot-iOS",
             devices: devices)
  end

  desc "Runs Tests for latest iOS"
  lane :test_ios do
    devices = get_devices()
    test(scheme: "BonMot-iOS",
         devices: devices)
  end

  desc "Runs Tests & Generates Code Coverage Reports for tvOS"
  lane :coverage_tvos do
    coverage(scheme: "BonMot-tvOS")
  end

  desc "Runs Tests for tvOS"
  lane :test_tvos do
    test(scheme: "BonMot-tvOS")
  end

  # Tests cannot be run on watchOS
  desc "Build for watchOS"
  lane :build_watchos do
    xcodebuild(scheme: "BonMot-watchOS",
               derivedDataPath: DERIVED_DATA_PATH)
  end
end

def test(scheme:, devices: nil, destination: nil)
  # NOTE: Running too many devices concurrently breaks CircleCI resource limits
  disable_concurrent_testing = false
  if ENV['CIRCLE_BUILD_NUM']
    disable_concurrent_testing = true
  end

  xcargs = ""
  if !ENV['SWIFT_VERSION'].nil?
    xcargs = "SWIFT_VERSION=#{ENV['SWIFT_VERSION']}"
  end

  begin
    scan(
      devices: devices,
      destination: destination,
      scheme: scheme,
      xcargs: xcargs,
      derived_data_path: DERIVED_DATA_PATH,
      disable_concurrent_testing: disable_concurrent_testing
    )
  rescue => ex
    # Don't fail the entire lane when running tests, but print failure to STDERR
    STDERR.puts ex
  end
end

def coverage(scheme:, devices: nil, destination: nil)
  scan_output_path = "#{BUILD_PATH}/#{scheme}/scan"

  # NOTE: Running too many devices concurrently breaks CircleCI resource limits
  disable_concurrent_testing = false
  if ENV['CIRCLE_BUILD_NUM']
    disable_concurrent_testing = true
  end

  begin
    scan(
      output_types: 'junit,html',
      devices: devices,
      destination: destination,
      scheme: scheme,
      output_directory: scan_output_path,
      code_coverage: true,
      derived_data_path: DERIVED_DATA_PATH,
      result_bundle: true,
      disable_concurrent_testing: disable_concurrent_testing
    )
  rescue => ex
    # Don't fail the entire lane when running tests, but print failure to STDERR
    STDERR.puts ex
  end

  result_bundle_path = Scan.cache[:result_bundle_path]

  # Extract coverage from Xcode 11 xcresult bundle
  absolute_result_bundle_path = "#{Dir.pwd}/../#{result_bundle_path}"
  absolute_coverage_path = "#{absolute_result_bundle_path}-coverage"
  sh("xcparse codecov #{absolute_result_bundle_path} #{absolute_coverage_path}")
  xccoverage_files = Dir.glob("#{absolute_coverage_path}/**/action.xccovreport").sort_by { |filename| File.mtime(filename) }.reverse
  xccov_file_direct_path = xccoverage_files.first

  slather_use_circleci = "false"

  if ENV['CIRCLE_BUILD_NUM']
    slather_use_circleci = "true"
  end

  xcov(
    project: PROJECT_NAME,
    scheme: scheme,
    output_directory: "#{BUILD_PATH}/#{scheme}/xcov",
    xccov_file_direct_path: xccov_file_direct_path
  )

  # Add binaries here as you create internal frameworks
  slather_binaries = ['BonMot']
  slather_output_directory = "#{BUILD_PATH}/#{scheme}/slather"

  # html and cobertura_xml output must be run separately
  slather(
    proj: PROJECT_NAME,
    scheme: scheme,
    binary_basename: slather_binaries,
    output_directory: slather_output_directory,
    html: "true",
    build_directory: DERIVED_DATA_PATH
  )
  # Using Cobertura XML allows us to upload to Codecov.io
  # Uploading to codecov is handled separately in the .circleci/config.yml
  slather(
    proj: PROJECT_NAME,
    scheme: scheme,
    binary_basename: slather_binaries,
    output_directory: slather_output_directory,
    circleci: slather_use_circleci,
    cobertura_xml: "true",
    build_directory: DERIVED_DATA_PATH
  )

  xchtmlreport(result_bundle_path: result_bundle_path,
               enable_junit: true)

  result_bundle_path
end

def get_devices()
  # The full list of iOS simulators available on CircleCI
  # https://circleci.com/docs/2.0/testing-ios/#supported-xcode-versions
  devices = []
	devices.push("iPhone SE")
	devices.push("iPhone X")
  devices.push("iPhone 11 Pro Max")
	devices.push("iPhone 8")
	devices.push("iPhone 8 Plus")
	devices.push("iPad Pro (10.5-inch)")
  devices
end
